package com.artislong.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;
import io.modelcontextprotocol.spec.McpSchema;
import org.springframework.ai.mcp.client.autoconfigure.NamedClientMcpTransport;
import org.springframework.ai.mcp.client.autoconfigure.SseHttpClientTransportAutoConfiguration;
import org.springframework.ai.mcp.client.autoconfigure.SseWebFluxTransportAutoConfiguration;
import org.springframework.ai.mcp.client.autoconfigure.properties.McpClientCommonProperties;
import org.springframework.ai.mcp.client.autoconfigure.properties.McpSseClientProperties;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.net.http.HttpClient;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 陈敏
 * @version McpWebClientConfiguration.java, v 1.0 2025 07 10 23:45 chenmin Exp $
 * Created on 2025 07 10
 */
@AutoConfiguration(after = SseWebFluxTransportAutoConfiguration.class)
@ConditionalOnClass({ McpSchema.class, McpSyncClient.class })
@ConditionalOnMissingClass("io.modelcontextprotocol.client.transport.WebFluxSseClientTransport")
@EnableConfigurationProperties({ McpSseClientProperties.class, McpClientCommonProperties.class })
public class McpWebClientConfiguration extends SseHttpClientTransportAutoConfiguration {

    /**
     * Creates a list of HTTP client-based SSE transports for MCP communication.
     *
     * <p>
     * Each transport is configured with:
     * <ul>
     * <li>A new HttpClient instance
     * <li>Server URL from properties
     * <li>ObjectMapper for JSON processing
     * </ul>
     * @param sseProperties the SSE client properties containing server configurations
     * @param objectMapperProvider the provider for ObjectMapper or a new instance if not
     * available
     * @return list of named MCP transports
     */
    @Bean
    @Override
    public List<NamedClientMcpTransport> mcpHttpClientTransports(McpSseClientProperties sseProperties,
                                                                 ObjectProvider<ObjectMapper> objectMapperProvider) {

        ObjectMapper objectMapper = objectMapperProvider.getIfAvailable(ObjectMapper::new);

        List<NamedClientMcpTransport> sseTransports = new ArrayList<>();

        for (Map.Entry<String, McpSseClientProperties.SseParameters> serverParameters : sseProperties.getConnections().entrySet()) {

            String baseUrl = serverParameters.getValue().url();
            String sseEndpoint = serverParameters.getValue().sseEndpoint() != null
                    ? serverParameters.getValue().sseEndpoint() : "/sse";
            var transport = HttpClientSseClientTransport.builder(baseUrl)
                    .sseEndpoint(sseEndpoint)
                    .clientBuilder(HttpClient.newBuilder())
                    .customizeRequest(httpRequestBuilder -> httpRequestBuilder.header("Authorization", "Bearer eyJraWQiOiJlMjMwYzU0MS05ZTljLTQ5MDMtODhhYy00MGU3NTE3MDgyZGIiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtY3AtY2xpZW50IiwiYXVkIjoibWNwLWNsaWVudCIsIm5iZiI6MTc1MzU0NDAyMiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwIiwiZXhwIjoxNzUzNTQ0MzIyLCJpYXQiOjE3NTM1NDQwMjIsImp0aSI6ImE5NjhmMDNkLTliYjAtNGRkMS05ZDM3LTk1ZmYyMmYxNDMyMiJ9.U-lsmctMvXbUevotcxSkPXSbRuZH_s_SOimW0QSZauwpd0TslUxhKRmleQ-XDXrFdVV4FpdNDzyV8zu3JJaUvIjJN6ktviMm6BZ39vaR9sWV416BTa_qv9qPub0J7s3Pnn17J3iGCyIVOX-lRFF393HAu0R0k1IIout5Q2mpbr758UdTDYQQYH9RcMBK3V3hvVhBes7hwpDAqCOSHNr0dwhUC_7I0X5jCVI4EA7HHbKkzST8NfQYKozlHyDsFKOroTJ8PzN7-cOWIpa66R4k0tAVwCx-q1NyL3ooTcyoMxMMHYJWFKuOt1nGIrW374XJW6EMD8uitUA7Y3KPsO0_pA"))
                    .customizeClient(httpClientBuilder -> httpClientBuilder.version(HttpClient.Version.HTTP_2))
                    .objectMapper(objectMapper)
                    .build();
            sseTransports.add(new NamedClientMcpTransport(serverParameters.getKey(), transport));
        }

        return sseTransports;
    }
}
